package org.bbl.db.mybatis.mysql;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.bbl.db.domain.BblId;
import org.bbl.db.mybatis.mapper.BaseMapper;
import org.bbl.db.mybatis.mapper.SearchResultMapper;

import java.util.ArrayList;
import java.util.List;

/**
 * @author biniamg
 * @since 11/15/12
 */

@Singleton
public class MyEntityResolverImpl implements MyEntityResolver {

    private final MyDataSource dataSource;

    @Inject
    public MyEntityResolverImpl( MyDataSource dataSource) {
        this.dataSource = dataSource;
    }

    public MyDataSource getDataSource() {
        return dataSource;
    }

    @Override
    public <T> T findById(Class<? extends BaseMapper<T>> clazz, int... ids) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            if(ids.length==1) {
            return mapper.findById(ids[0]);
            }else if(ids.length==2){
                return mapper.findByIdAndLanguage(ids[0],ids[1]);
            }

        } finally {
            session.close();
        }
        return null;
    }

    @Override
    public <T> List<T> findAll(Class<? extends BaseMapper<T>> clazz) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            return mapper.findAll();
        } finally {
            session.close();
        }
    }


    @Override
    public <T> List<T> findAll(Class<? extends BaseMapper<T>> clazz, String tableName) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            return mapper.findByLanguage(tableName);
        } finally {
            session.close();
        }
    }

    @Override
    public <T> List<T> findByParentId(Class<? extends BaseMapper<T>> clazz, int parentId) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            return mapper.findByParentId(parentId);
        } finally {
            session.close();
        }
    }

    @Override
    public <T> T findByIdentifier(Class<? extends BaseMapper<T>> clazz, int languageId, String identifier) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            return mapper.findByIdentifier(languageId, identifier);
        } finally {
            session.close();
        }
    }

    @Override
    public <T> List<T> findMySibling(Class<? extends BaseMapper<T>> clazz, int languageId, String identifier) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            return mapper.findMySibling(languageId, identifier);
        } finally {
            session.close();
        }
    }

    @Override
    public <T> List<T> findByKeyId(Class<? extends BaseMapper<T>> clazz, String language, int bookId, int chapterId) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            return mapper.findByKeyId(language, bookId, chapterId);
        } finally {
            session.close();
        }
    }

    @Override
    public <T> List<T> findByLike(Class<? extends BaseMapper<T>> clazz, String tableName, int bookIdS, int bookIdE, String key) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            RowBounds rowBounds = new RowBounds(0, 200);
            return mapper.findByLike(tableName, bookIdS, bookIdE, "%" + key + "%", "%" + key + "%", rowBounds);
        } finally {
            session.close();
        }
    }

    @Override
    public <T> List<T> findByApproximation(Class<? extends BaseMapper<T>> clazz, String tableName,
                                           String tableName2, int bookIdS, int bookIdE,
                                           String key1, String key2) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            RowBounds rowBounds = new RowBounds(0, 200);
            return mapper.findByApproximation(tableName2, tableName, bookIdS, bookIdE,
                    "%" + key1 + "%", key1, "%" + key2 + "%", key2, rowBounds);
        } finally {
            session.close();
        }
    }


    @Override
    public <T> void delete(Class<? extends BaseMapper<T>> clazz, int languageId) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            mapper.delete(languageId);
            session.commit();
            //  } catch (Exception e) {                  logger.error(e.getMessage(), e);                  return null;
        } finally {
            session.close();
        }
    }


    @Override
    public <T> void insert(Class<? extends BaseMapper<T>> clazz, T t) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            mapper.insert(t);
            session.commit();
            //  } catch (Exception e) {                  logger.error(e.getMessage(), e);                  return null;
        } finally {
            session.close();
        }
    }


    @Override
    public <T> void insertDynamicTable(Class<? extends BaseMapper<T>> clazz, String param1, T t) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper<T> mapper = session.getMapper(clazz);
            mapper.insertDynamicTable(param1, t);
            session.commit();
            //  } catch (Exception e) {                  logger.error(e.getMessage(), e);                  return null;
        } finally {
            session.close();
        }
    }

    @Override
    public void truncate(String tableName) {
        final SqlSession session = dataSource.getSession();
        try {
            BaseMapper mapper = session.getMapper(BaseMapper.class);
            mapper.truncate(tableName);
            session.commit();
            //  } catch (Exception e) {                  logger.error(e.getMessage(), e);                  return null;
        } finally {
            session.close();
        }
    }

    @Override
    public <T> List<T> findLinking(Class<? extends BaseMapper<T>> clazz,String tableName, int param2, int param3, int param4) {
        final SqlSession session = dataSource.getSession();
         List<Integer> list = new ArrayList<Integer>();
         try {
             BaseMapper<T> mapper =  session.getMapper(clazz);
             RowBounds rowBounds = new RowBounds(0, 200);
             return mapper.findLinking(tableName, param2, param3, param4,rowBounds);

         } finally {
             session.close();
         }
    }

    @Override
    public List<Integer> search(String tableName, int param2, int param3, int param4, String param5) {
        final SqlSession session = dataSource.getSession();
        List<Integer> list = new ArrayList<Integer>();
        try {
            SearchResultMapper mapper = session.getMapper(SearchResultMapper.class);
            RowBounds rowBounds = new RowBounds(0, 200);
            List<BblId> search = mapper.search(tableName, param2, param3, param4, param5, rowBounds);
            for (BblId bblId : search) {
                list.add(bblId.getVerseId());
            }
            return list;
        } finally {
            session.close();
        }
    }
}
